<template>
  <div v-if="Show" id="menu-wrapper" :class="visible ? 'visible' : ''">
    <div :class="expand ? 'expand' : ''" id="article-menu">
      <template v-if="visible">
        <div class="content">
          <div class="title">目录</div>
          <div class="progress">
            您已经阅读了
            <span class="progress-val">{{ progress }}</span
            >%
            <q-linear-progress stripe size="10px" :value="progress / 100" />
          </div>
          <!-- <div class="progress-bar" :style="`width:${progress}%`"></div> -->
          <div class="inner-content">
            <directory-item
              :List="list"
              :Active_index="active_index"
            ></directory-item>
          </div>
        </div>
        <div class="dragbar">
          <span class="arrow-wrapper">
            <span class="arrow" @click="ExpandDirectory(!expand)">
              <q-icon v-if="expand" name="mdi-chevron-left" />
              <q-icon v-else name="mdi-chevron-right" />
            </span>
          </span>
        </div>
      </template>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator';
import DirectoryItem from './directoryItem.vue';
import { treeNode } from 'src/models/treeNode';
import { bus } from './recusion-bus';
import { scroll } from 'quasar';
const { getScrollTarget, setScrollPosition, getScrollPosition } = scroll;

@Component<postDirectory>({
  created() {
    bus.$off('jump');
    bus.$on('jump', (item: treeNode) => {
      this.jump(item);
    });
  },
  mounted() {
    // $('#app').stop(true);
    this.generateDirectory(this.DomId);
    window.addEventListener('scroll', this.FindAnchor);
    window.addEventListener('resize', this.resize);
  },
  components: { DirectoryItem },

  beforeDestroy() {
    // $("#app").css("padding-left", 0);
    this.ExpandDirectory(false);

    window.removeEventListener('scroll', this.FindAnchor);
    window.removeEventListener('resize', this.resize);
  }
})
export default class postDirectory extends Vue {
  @Prop({ type: Boolean, required: true, default: true })
  readonly Show!: boolean;

  @Prop({ type: String, required: true, default: '' })
  readonly DomId!: string;

  @Prop({ type: Number, required: false, default: 25 })
  readonly Offset!: number;

  private list: Array<treeNode> = [];

  private expand: boolean = false;

  private isEmpty: boolean = true;

  private domArray: Array<any> = [];

  private active_index: number = -1;

  private anchorMoving: boolean = false;

  private progress: number = 0;

  // get rotateDirection(): string {
  //   if (this.loaded) {
  //     return "on";
  //   } else {
  //     return "closed";
  //   }
  // }

  get visible(): Boolean {
    // return !this.isEmpty && !isMobile();
    return !this.isEmpty;
  }

  //根据文章制作目录

  public generateDirectory(id: string) {
    let trees: Array<treeNode> = [];
    // console.log(isMobile(), process.browser);
    // process.browser && !isMobile()
    if (true) {
      let dom = document.getElementById(id);
      this.list = [];
      this.domArray = [];
      if (dom) {
        var domArray: Array<any> = Array.from(
          dom.querySelectorAll(
            'h1:not(pre),h2:not(pre),h3:not(pre),h4:not(pre),h5:not(pre),h6:not(pre)'
          )
        );

        let excludePre = (el: HTMLElement, arr: string[] = []): string[] => {
          if (el.tagName.toUpperCase() == 'PRE') {
            arr.push('PRE');
            return arr;
          }
          if (el.parentElement) {
            arr = excludePre(el.parentElement, arr);
          }
          return arr;
        };
        domArray = domArray.filter(n => {
          var arr = excludePre(n);
          return !arr.includes('PRE');
        });
        this.domArray = domArray;
        this.isEmpty = domArray.length == 0;
        if (this.isEmpty) return;
        for (let i = 0; i < domArray.length; i++) {
          let element = domArray[i];

          let level = element.tagName.substring(1);
          var node: treeNode = new treeNode();
          node.Tag = element.tagName;
          node.Text = element.textContent;
          node.Children = [];
          node.SerialNo = '';
          node.Level = -1;
          node.Index = i;
          trees.push(node);
          element.treeNode = node;

          for (let j = i - 1; j > 0; j--) {
            let prevElement = domArray[j];
            let prevLevel = prevElement.tagName.substring(1);

            if (prevLevel < level) {
              node.Parent = trees[j];
              trees[j].Children.push(node);
              node.Deleted = true;

              break;
            }
          }
        }
        // trees.splice(
        //   trees.findIndex((e) => e.Deleted),
        //   1
        // );
        for (var k = 0; k < trees.length; k++) {
          if (!trees[k].Deleted) {
            this.list.push(trees[k]);
          }
        }

        // this.list = trees;

        this.list = this.recursive(this.list, 1);
        this.ExpandDirectory(true);
      }
    }
  }
  //递归目录层级
  public recursive(nodes: treeNode[], level: number): treeNode[] {
    nodes.forEach(n => {
      if (n.Children && n.Children.length > 0) {
        this.recursive(n.Children, level + 1);
      }
      n.Level = level;
    });
    return nodes;
  }

  //点击目录 跳转
  public jump(item: treeNode): void {
    if (item.Index == this.active_index) return;
    let top = this.domArray[item.Index].offsetTop;

    // console.log(this.domArray[index].offsetTop);
    this.active_index = item.Index;

    this.list.forEach(element => {
      if (item != element) element.Expand = false;
    });
    item.Expand = true;
    this.anchorMoving = true;
    item.ExpandNode();
    // if (item.Parent) {
    //   item.Parent.Expand = true;
    // }
    window.removeEventListener('scroll', this.FindAnchor);
    const el = document.querySelector('html');
    const duration = 400;
    setScrollPosition(el as HTMLElement, top, duration);

    this.CalcReadPercent();
    this.anchorMoving = false;
    setTimeout(() => {
      window.addEventListener('scroll', this.FindAnchor);
    }, 400);

    // $('html')
    //   .stop()
    //   .animate(
    //     {
    //       scrollTop: top
    //     },
    //     800,
    //     () => {
    //       window.addEventListener('scroll', this.FindAnchor);
    //       this.CalcReadPercent();
    //       this.anchorMoving = false;
    //     }
    //   );
  }

  public FindAnchor(e: any): void {
    if (this.domArray == null || this.domArray.length == 0) return;

    if (this.anchorMoving) return;

    this.anchorMoving = true;
    var post_content_dom = document.getElementById(this.DomId);
    if (post_content_dom) {
      var bodytop =
        document.documentElement.scrollTop || document.body.scrollTop;
      let currentNode: any;
      this.domArray.forEach((element, index) => {
        let diffHeitht = bodytop - element.offsetTop;

        if (bodytop > element.offsetTop - this.Offset) {
          this.active_index = index;

          currentNode = element.treeNode;

          return true;
        }
      });
      if (currentNode) {
        currentNode.ExpandNode(currentNode);
        this.$nextTick(() => {
          currentNode.Collapse(this.list);
        });
      }
      this.anchorMoving = false;
      this.CalcReadPercent();
    }
  }

  public CalcReadPercent(): void {
    var post_content_dom = document.getElementById(this.DomId);
    if (post_content_dom) {
      var postheight = post_content_dom.offsetHeight;
      var postTop = post_content_dom.offsetTop;
      var bodytop =
        document.documentElement.scrollTop || document.body.scrollTop;
      if (bodytop <= postTop) {
        this.progress = 0;
      } else if (bodytop > postheight + postTop) {
        this.progress = 100;
      } else {
        this.progress = Math.round(((bodytop - postTop) / postheight) * 100);
      }
    }
  }

  public ExpandDirectory(flag: boolean): void {
    this.expand = flag;
    const dom = document.getElementById('q-app');
    if (!dom) return;
    if (document.body.clientWidth < 1000) {
      return;
    }
    if (this.expand) {
      const width = document.getElementById('article-menu')?.clientWidth + 'px';
      dom.style.paddingLeft = width;
    } else {
      dom.style.paddingLeft = '0px';
    }
  }

  public resize() {
    const dom = document.getElementById('q-app');
    if (!dom) return;
    if (document.body.clientWidth >= 1000) {
      if (this.expand) {
        const width =
          document.getElementById('article-menu')?.clientWidth + 'px';
        dom.style.paddingLeft = width;
      } else {
        dom.style.paddingLeft = '0px';
      }
    } else {
      dom.style.paddingLeft = '0px';
    }
  }
}
</script>
<style lang="scss" scoped>
@media screen and (max-width: 1024px) {
  #article-menu {
    left: -100% !important;
  }
  #toggle-sidebar {
    display: none;
  }
}
#article-menu {
  position: fixed;
  top: 0;
  left: -100%;
  z-index: 1001;
  width: 300px;
  height: 100%;
  max-width: 300px;
  opacity: 0.9;
  background: var(--card-bg);
  will-change: left;
  transition: 0.4s;
  // box-shadow: 1px 8px 12px var(--text-black);
  .content {
    padding: 2rem 1rem;
    overflow: auto;
  }
  .dragbar {
    position: absolute;
    z-index: 202;
    top: 0;
    bottom: 0;
    right: 0;
    width: 16px;
    user-select: none;
    cursor: ew-resize;
    .arrow-wrapper {
      position: absolute;
      display: inline-block;
      top: 135px;
      width: 32px;
      height: 32px;
      cursor: pointer;
      z-index: 2;
      .arrow {
        transition: 0.3s;
        display: block;
        width: 27px;
        background-color: #fff;
        border: 1px solid #e8e8e8;
        border-radius: 50%;
        transition: all 0.1s ease-in-out;
        font-size: 12px;
        text-align: center;
        line-height: 24px;
        //  box-shadow: 0 0.5px 0.7px rgba(0 0 0, 1);
        box-shadow: 0 0.1px 0.9px rgba(0, 0, 0, 1);
        font-size: 20px;
        &:hover {
          color: #25b864;
          border-color: #25b864;
        }
      }
    }
    &::before {
      content: '';
      position: absolute;
      top: 0;
      bottom: 0;
      right: 0;
      width: 16px;
      background-color: var(--card-white);
      transition: all 0.2s ease-in-out;
    }
    &::after {
      content: '';
      transition: backgroundColor 0.2s ease-in-out;
      position: absolute;
      top: 0;
      bottom: 0;
      right: 0;
      width: 1px;
      background-color: #bfbfbf;
    }
  }
  #toggle-sidebar {
    display: none;
  }
  transition: left 0.3s;

  #toggle-sidebar {
    display: block;
  }
  .title {
    text-align: center;
    font-size: 20px;
    font-weight: 600;
    color: #333;
  }
  .progress {
    color: #333;
    font-size: 15px;
    padding: 5px;
    .progress-val {
      font-weight: 700;
    }
  }
  .progress-bar {
    color: #333;
    height: 1px;
    background: #333;
    transition: 0.5s;
  }
  .inner-content {
    max-height: calc(100vh - 100px);
    overflow: auto;
  }
  #toggle-sidebar {
    position: fixed;
    top: 50%;

    z-index: 100;
    font-size: 16px;
    cursor: pointer;
    transform: none;
    width: 30px;
    // transition: all 0.2s;
    i {
      position: relative;
    }
    &.on {
      left: 270px;
      &:hover {
        i {
          animation: move-left 1.5s linear infinite;
        }
      }

      // transform: rotate(180deg);
    }
    &.closed {
      left: 16px;
      &:hover {
        i {
          animation: move-right 1.5s linear infinite;
        }
      }
    }
  }

  @keyframes move-right {
    0% {
      left: 0%;
      opacity: 0;
    }
    70% {
      left: 70%;
      opacity: 1;
    }
    100% {
      left: 100%;
      opacity: 0;
    }
  }

  @keyframes move-left {
    0% {
      right: 0%;
      opacity: 0;
    }
    70% {
      right: 70%;
      opacity: 1;
    }
    100% {
      right: 100%;
      opacity: 0;
    }
  }
  @for $i from 1 through 6 {
    .ar-delay-#{$i}s {
      animation-delay: (0.1s * $i) !important;
    }
  }
  // .ar-delay-1s {
  //   animation-delay: 0.1s !important;
  // }
  // .ar-delay-2s {
  //   animation-delay: 0.2s !important;
  // }
  // .ar-delay-3s {
  //   animation-delay: 0.3s !important;
  // }
}
#menu-wrapper.visible {
  #article-menu {
    left: -284px;
    &.expand {
      left: 0;
      transition: 0.4s;
    }
  }
}
</style>

<style>
#q-app {
  transition: 0.4s;
}
</style>
